package com.kehutong.house.service;

import com.kehutong.common.DoveClient;
import com.kehutong.common.permission.DataPermissionQuery;
import com.kehutong.common.permission.PermissionNameDto;
import com.kehutong.common.permission.UserLoginInfo;
import com.kehutong.common.util.Token;
import com.kehutong.house.entity.Building;
import com.kehutong.house.enums.BuildType;
import com.kehutong.house.enums.PropertyType;
import org.coraframework.inject.Inject;
import org.coraframework.json.JSONArray;
import org.coraframework.json.JSONObject;
import org.coraframework.logger.Logger;
import org.coraframework.logger.LoggerFactory;
import org.coraframework.mvc.http.ReqMapping;
import org.coraframework.mvc.http.result.Result;
import org.coraframework.mvc.webservice.WebService;
import org.coraframework.orm.Pool;
import org.coraframework.orm.exception.ORMException;
import org.coraframework.orm.jdbc.JdbcSession;
import org.coraframework.orm.jdbc.execute.entity.FindArray;
import org.coraframework.util.EnumUtil;
import org.coraframework.util.Objects;

import com.kehutong.house.entity.Community;

import java.util.*;

@WebService("/basic/community/service")
public class CommunityService {

	private final static String businessType = "1100";

	private static final Logger logger = LoggerFactory.getLogger(CommunityService.class);

	@Inject
	private JdbcSession jdbcSession;
	@Inject
	private HouseService houseService;
	@Inject
	private DoveClient doveClient;
	@Inject
	private BasicService basicService;


    @ReqMapping("/list")
    public Object list(JSONObject jsonObject) {
    	return jdbcSession.findArray(Community.class)
				.in(jsonObject, "id")
				.in(jsonObject, "parent_id")
    			.like(jsonObject, "name", "viewName", "area_ids", "area_names","employee_ids")
				.eq("deleted", false).exe();
    }

	@ReqMapping("/get")
    public Object get(Community item) throws Exception {
		Map<String,JSONObject> departmentMap = getDepartmentMap(Arrays.asList(item.getParent_id()));
		Map<String,JSONObject> employeeMap = getEmployeeMap(item.getEmployee_ids());
		setParentName(departmentMap, employeeMap, item);
		return item;
    }

    @ReqMapping("/save")
    public Object save(Token token, Community community) throws Exception {
		// 增加校验不允许有相同的小区名称
		Community item = jdbcSession.findOne(Community.class)
				.eq("name", community.getName())
				.eq("deleted", false)
				.exe();

		if(Objects.nonNull(item)){
			return Result.error(0, "已有当前小区名称，请修改后重试");
		}

		try {
			community.setCreate_by(token.getUsername());
			community.setCreateUserId(token.getUuid());
			community.setCreateDepartment(token.getDepartments());
			community.setCreateChildDepartment(getChildDepartments(token.getDepartments()));

			// 增加部门转换的归属记录
			saveAttributeRecord(token, community, true);

			// 更新小区标签信息
			List<String> tags = this.saveOrUpdateTag(community);
			if(Objects.nonEmpty(tags)){
				community.setTags(tags);
			}

			jdbcSession.insert(community);
		} catch (ORMException e){
			return Result.error(0, "新增小区失败，请联系管理员！");
		}

		basicService.saveOperateRecord(token, community.getId(), businessType, "1", "");

		return Result.success(community);
    }

    @ReqMapping("/update")
    public Object update(Token token, Community community, JSONObject jsonObject) throws Exception {
		// 增加校验不允许有相同的小区名称
		Community item = jdbcSession.findOne(Community.class)
				.eq("name", community.getName())
				.noEq("id", community.getId())
				.eq("deleted", false)
				.exe();

		if(Objects.nonNull(item)){
			return Result.error(0, "已有当前小区名称，请修改后重试");
		}

		try {
			// 增加部门转换的归属记录
			saveAttributeRecord(token, community, false);

			// 更新小区标签信息
			List<String> tags = this.saveOrUpdateTag(community);
			if(Objects.nonEmpty(tags)){
				community.setTags(tags);
			}

			jdbcSession.updateById(community);
		} catch (ORMException e){
			return Result.error(0, "修改小区失败，请联系管理员！");
		}

		Boolean tagSetting = jsonObject.getBoolean("tagSetting");
		if(Objects.nonNull(tagSetting) && tagSetting){
			basicService.saveOperateRecord(token, community.getId(), businessType, "5", "");
		} else {
			basicService.saveOperateRecord(token, community.getId(), businessType, "2", "");
		}
		return Result.success();
    }

    @ReqMapping("/delete")
	public Object delete(Community item) {
		List<Building> builds = jdbcSession.findArray(Building.class)
				.eq("communityNo", item.getId())
				.eq("deleted", false)
				.exe();
		if(Objects.nonEmpty(builds)){
			return Result.error(0, "需先删除该小区下的楼栋，再删除该小区！");
		}
		if (Objects.nonNull(item)) {
			item.setDeleted(true);
			jdbcSession.updateById(item);
		}
		return Result.success();
	}
	@ReqMapping("/saveThridBatch")
	public Object saveThridBatch(JSONObject jsonObject){
		String opType=jsonObject.getString("opType");
		JSONArray communityList=jsonObject.getJSONArray("communityList");
		JSONArray backJsonArray=new JSONArray();
		for(int i=0,len=communityList.size();i<len;i++){
			JSONObject communityObj=communityList.getJSONObject(i);
			String communityName=communityObj.getString("communityName");
			String communityId=communityObj.getString("communityId");
			if("1".equals(opType)){ //增加
				Community community=Pool.newInstance(Community.class);
				community.setName(communityName);
				jdbcSession.insert(community);
				JSONObject middleRelationJson=new JSONObject();
				middleRelationJson.put("thirdId",communityId); //第三方id
				middleRelationJson.put("khtId",community.getId()); //客户通id
				backJsonArray.add(middleRelationJson);
			}else if("2".equals(opType)&&"3".equals(opType)){ //修改
				Community community=jdbcSession.findById(Community.class,communityId);
				community.setName(communityName);
				if("3".equals(opType)){
					community.setDeleted(true); //逻辑删除
				}else {
					community.setName(communityName);
				}
				jdbcSession.updateById(community);
			}else{
				logger.info("opType类型错误！");
			}
		}
		return backJsonArray;
	}
	@ReqMapping("/permissionList")
	public Object permissionList(JSONObject jsonObject) {
		FindArray<Community> find = jdbcSession.findArray(Community.class)
				.in(jsonObject, "id")
				.in(jsonObject, "parent_id")
				.like(jsonObject, "name", "viewName", "area_ids", "area_names")
				.eq("deleted", false)
				.order("createTime", "desc");

		PermissionNameDto dto = houseService.getCommunityPermissionNameDto();
		UserLoginInfo userLoginInfo = JSONObject.parseObject(jsonObject.toJSONString(), UserLoginInfo.class);
		houseService.setDataSql(find, dto, jsonObject, userLoginInfo);
		List<Community> list = find.exe();
		return list;
	}

	public Object permissionQuery(JSONObject jsonObject) {
		FindArray<Community> find = jdbcSession.findArray(Community.class)
				.like(jsonObject, "name")
				.eq("deleted", false)
				.order("createTime", "desc");

		PermissionNameDto dto = houseService.getCommunityPermissionNameDto();
		DataPermissionQuery.setAllDataSql(find, dto, null);
		List<Community> list = find.exe();
		return list;
	}

	public Object getCommunityTransfer (JSONObject jsonObject) throws Exception {
		JSONArray data = new JSONArray(2);

		Community community = Pool.get(Community.class, jsonObject.getString("communityNo"));

		JSONArray employees = new JSONArray();
		List<JSONObject> array = new ArrayList<>();

		if(Objects.nonEmpty(community.getEmployee_ids())){
			employees = getEmployees(community.getEmployee_ids(), jsonObject.getString("name"));
		}
		employees.forEach(item-> {
			JSONObject employee = (JSONObject) item;
			array.add(employee2JSONObject(community.getId(), employee));
		});

		JSONObject root = community2JSONObject(community);
		data.add(root);
		data.add(array);
		return Result.success(data);
	}

	private JSONObject community2JSONObject(Community community) {
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("id", community.getId());
		jsonObject.put("pid", community.getParent_id());
		jsonObject.put("label", community.getName());
		return jsonObject;
	}

	private JSONObject employee2JSONObject(String communityId, JSONObject employee) {
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("id", employee.getString("id"));
		jsonObject.put("pid", communityId);
		jsonObject.put("name", employee.getString("name"));
        jsonObject.put("label", employee.getString("name"));
		jsonObject.put("avatar", employee.getString("avatar"));
		jsonObject.put("user", true);
		return jsonObject;
	}

	public JSONArray getEmployees(List<String> employeeNos) throws Exception {
		JSONObject result = doveClient.post("/basic/employee/service/list", http->{
			JSONObject body = new JSONObject();
			body.put("id", employeeNos);

			body.put("pageNo", 1);
			body.put("pageSize", 1000000);

			http.setBody(body.toString());
		});

		JSONArray data = result.getJSONObject("data").getJSONArray("list");

		if (Objects.isNull(data)) {
			return null;
		}

		return data;
	}

	public JSONArray getEmployees(List<String> employeeNos, String name) throws Exception {
		JSONObject result = doveClient.post("/basic/employee/service/list", http->{
			JSONObject body = new JSONObject();
			body.put("id", employeeNos);
			body.put("name", name);

			body.put("pageNo", 1);
			body.put("pageSize", 1000000);

			http.setBody(body.toString());
		});

		JSONArray data = result.getJSONObject("data").getJSONArray("list");

		if (Objects.isNull(data)) {
			return null;
		}

		return data;
	}

    public boolean isCommunityExist(String communityNo) {
    	if (Objects.isEmpty(communityNo)) {
    		return false;
    	}
    	
    	Community community = jdbcSession.findById(Community.class, communityNo);
    	
    	return Objects.nonNull(community);
    	
    }

	public void saveAttributeRecord(Token token ,Community com, boolean isSave) throws Exception {
		JSONObject json = new JSONObject();
		json.put("businessId", com.getId());
		json.put("businessType", businessType);
		json.put("currentNo", com.getParent_id());
		json.put("currentNos", com.getParent_ids());
		if(isSave){
			basicService.saveAttributeRecord(token, json);
		} else {
			Community old = Pool.get(Community.class, com.getId());
			if(Objects.isEmpty(com.getParent_id())){
				com.setParent_id("");
			}
			if(Objects.isEmpty(old.getParent_id())){
				old.setParent_id("");
			}

			if(!Objects.equal(old.getParent_id(),com.getParent_id())){
				json.put("beforeNo", old.getParent_id());
				json.put("beforeNos", old.getParent_ids());
				basicService.saveAttributeRecord(token, json);
			}
		}

	}

	public List<String> getChildDepartments(List<String> departments) throws Exception {
		JSONObject result = doveClient.post("/basic/department/service/getChildDepartments", http->{
			JSONObject body = new JSONObject();
			body.put("pidList", departments);
			http.setBody(body.toString());
		});

		if (result.getIntValue("code") == 200) {
			JSONArray data = result.getJSONArray("data");
			if(Objects.nonEmpty(data)){
				return JSONObject.parseArray(data.toJSONString(), String.class);
			}
		}
		return new ArrayList<>();
	}

	/**
	 * 报错或更新用户的业务标签
	 * @param community 小区信息
	 * @throws Exception
	 */
	public List<String> saveOrUpdateTag(Community community) throws Exception{
		JSONArray tagDatas = new JSONArray();

		List<String> buildTypes = community.getBuildType();
		if(Objects.nonEmpty(buildTypes)){
			JSONObject tagObj = new JSONObject();
			tagObj.put("tagGroupName", "建筑类别");
			List <String> tagNames = new ArrayList<>();
			for (String id: buildTypes) {
				String name = EnumUtil.getEnum(BuildType.class, id).getDesc();
				tagNames.add(name);
			}
			tagObj.put("tagName", String.join(",", tagNames));
			tagDatas.add(tagObj);
		}

		List<String> propertyTypes = community.getPropertyType();
		if(Objects.nonEmpty(propertyTypes)){
			JSONObject tagObj = new JSONObject();
			tagObj.put("tagGroupName", "物业类别");
			List <String> tagNames = new ArrayList<>();
			for (String id: propertyTypes) {
				String name = EnumUtil.getEnum(PropertyType.class, id).getDesc();
				tagNames.add(name);
			}
			tagObj.put("tagName", String.join(",", tagNames));
			tagDatas.add(tagObj);
		}

		String propertyYear = community.getPropertyYear();
		if(Objects.nonEmpty(propertyYear)){
			JSONObject tagObj = new JSONObject();
			tagObj.put("tagGroupName", "产权年限");
			tagObj.put("tagName", propertyYear);
			tagDatas.add(tagObj);
		}

		if (Objects.nonEmpty(tagDatas)) {
			JSONObject result=doveClient.post("/admin/business/tag/service/batch/add", (http) -> {
				JSONObject body = new JSONObject();
				body.put("dataList", tagDatas);
				http.setBody(body.toJSONString());
			});

			if (result.getIntValue("code") == 200) {
				JSONArray data = result.getJSONArray("data");
				if(Objects.nonEmpty(data)){
					List<String> tagIds = new ArrayList<>();
					List<JSONObject> tags = JSONObject.parseArray(data.toJSONString(), JSONObject.class);
					tags.forEach(tag -> {
						tagIds.add(tag.getString("id"));
					});
					return tagIds;
				}
			}
		}
		return null;
	}

	public Map<String,JSONObject> getDepartmentMap(List<String> departmentIds) throws Exception {
		JSONObject result = doveClient.post("/basic/department/service/list", http->{
			JSONObject body = new JSONObject();
			body.put("id", departmentIds);
			http.setBody(body.toString());
		});

		JSONArray data = result.getJSONArray("data");

		if (Objects.isNull(result) || Objects.isNull(data)) {
			return new HashMap<>();
		}

		Map<String,JSONObject> departmentMap = new HashMap<>();
		data.forEach(item->{
			JSONObject obj = (JSONObject) item;
			departmentMap.put(obj.getString("id"), obj);
		});

		return departmentMap;
	}

	public Map<String,JSONObject> getEmployeeMap(List<String> employeeIds) throws Exception {
		JSONObject result = doveClient.post("/basic/employee/service/list", http->{
			JSONObject body = new JSONObject();
			body.put("id", employeeIds);
			body.put("pageNo", 1);
			body.put("pageSize", 1000000);
			http.setBody(body.toString());
		});

		JSONArray data = result.getJSONObject("data").getJSONArray("list");

		if (Objects.isNull(data)) {
			return null;
		}

		Map<String,JSONObject> employeeMap = new HashMap<>();
		data.forEach(item->{
			JSONObject obj = (JSONObject) item;
			employeeMap.put(obj.getString("id"), obj);
		});

		return employeeMap;
	}

	public void setParentName(Map<String,JSONObject> departmentMap, Map<String,JSONObject> employeeMap, Community item){

		JSONObject department = departmentMap.get(item.getParent_id());
		if(Objects.nonNull(department)){
			item.setParent_deleted(department.getBoolean("deleted"));
			item.setParent_name(department.getString("name"));
		}

		List<String> employee_names = new ArrayList<>();
		item.getEmployee_ids().forEach(id ->{
			JSONObject employee = employeeMap.get(id);
			if(Objects.nonNull(employee)){
				employee_names.add(employee.getString("name"));
			}
		});
		item.setEmployee_names(employee_names);
	}
}
